﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using ZaxLib.Collections;

namespace ZaxLib.Web.UI.WebControls
{
    [
		DefaultProperty("Text"),
		ParseChildren(true, "GridItems"),
		ToolboxData("<{0}:GridView runat=server> </{0}:GridView>")
	]
	public class GridView : CompositeDataBoundControl
	{

		#region Data Structures

		private ArrayList _gridItems;

		#endregion

		#region Parameters

		[Bindable(false),
		CssClassProperty(),
		Description("Table head row class definition"),
		Category("Table Appearance"),
		DefaultValue("")]
		public String HeadRowClass
		{
			get
			{
				String s = ViewState["HeadCellClass"] as String;
				return (s == null ? "CellHead" : s);
			}
			set
			{
				ViewState["HeadCellClass"] = value;
			}
		}

		[Bindable(false),
		CssClassProperty(),
		Description("Main table row class"),
		Category("Table Appearance"),
		DefaultValue("")]
		public String RowClass
		{
			get
			{
				String s = ViewState["RowClass"] as String;
				return (s == null ? "Row1" : s);
			}
			set
			{
				ViewState["RowClass"] = value;
			}
		}

		[Bindable(false),
		CssClassProperty(),
		Description("Alternate table row class"),
		Category("Table Appearance"),
		DefaultValue("")]
		public String AlternateRowClass
		{
			get
			{
				String s = ViewState["AlternateRowClass"] as String;
				return (s == null ? "Row2" : s);
			}
			set
			{
				ViewState["AlternateRowClass"] = value;
			}
		}// End parameter AlternateRowClass

		private IDataGrid _data = null;
		/// <summary>
		/// Grid Data for control
		/// </summary>
		public IDataGrid Data
		{
			get
			{
				if (_data == null)
				{
					_data = new CDataGrid();
				}
				return _data;
			}
			set
			{
				_data = value;
				OnDataBinding(new GridEventArgs(Data));
			}
		}// End parameter Data

		[Bindable(true),
		CssClassProperty(),
		Description("Number of rows to display per page."),
		Category("Table Appearance"),
		DefaultValue("")]
		public int RowsPerPage
		{
			get
			{
				int i = Data.Count;
				if (ViewState["RowsPerPage"] != null)
				{
					i = Convert.ToInt32(ViewState["RowsPerPage"]);
				}

				return i;
			}
			set
			{
				ViewState["RowsPerPage"] = value;
			}
		}

		[Bindable(true),
		CssClassProperty(),
		Description("Row to start displaying results"),
		Category("Table Appearance"),
		DefaultValue("")]
		public int StartRow
		{
			get
			{
				int i = 0;
				if (ViewState["StartRow"] != null)
				{
					i = Convert.ToInt32(ViewState["StartRow"]);
				}

				return i;
			}
			set
			{
				ViewState["StartRow"] = value;
			}
		}

		[
			Category("Behavior"),
			Description("Element in the grid to be drawn"),
			DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
			PersistenceMode(PersistenceMode.InnerDefaultProperty)
		]
		public ArrayList GridItems
		{
			get
			{
				if (_gridItems == null)
				{
					_gridItems = new ArrayList();
				}

				return _gridItems;
			}
		}// End parameter GridItems

		#endregion

		#region Writer Methods

		protected void ControlWrite(HtmlTextWriter writer)
		{
			RenderChildren(writer);
		}

		#endregion

		#region Render Methods

		protected override void RenderContents(HtmlTextWriter writer)
		{
			base.RenderContents(writer);
		}

		protected override void RenderChildren(HtmlTextWriter writer)
		{
			StringWriter sWriter = new StringWriter();
			HtmlTextWriter htWriter = new HtmlTextWriter(sWriter);
			base.RenderChildren(htWriter);
			// Flush witting and close
			htWriter.Flush();
			htWriter.Close();
			htWriter.Dispose();

			writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass);
			writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
			writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
			writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
			writer.RenderBeginTag(HtmlTextWriterTag.Table);
			writer.WriteLine(sWriter.ToString());
			writer.RenderEndTag();

			sWriter.Close();
			sWriter.Dispose();
		}

		protected override int CreateChildControls(IEnumerable data, bool dataBinding)
		{
			int Count = 0;
			// TotalColumns is used in the table cells for the header and footer
			int TotalColumns = 0;
			if (data != null)
			{
				// We need to do something here
				ClearChildState();
				foreach (IGridItem item in GridItems)
				{
					if (item is GridData)
					{
						int idx = 0;
						GridData gData = item as GridData;
						foreach (Dictionary<String, Object>gItem in Data)
						{
							if (idx < StartRow)
							{
								idx++;
								continue;
							}// Endif idx less than StartRow

							GridData nData = new GridData();
							nData.GridItems = gData.GridItems;
							nData.SetData(gItem);
							nData.CssClass = (idx++ % 2 == 0 ? RowClass : AlternateRowClass);
							Controls.Add(nData);
							if (idx > RowsPerPage) break;
							Count++;
							if (idx >= RowsPerPage) break;
						}// End foreach gItem in Data
						
						// Check if total cells is more then TotalColumns
						if (item.Data.Cells.Count > TotalColumns)
						{
							TotalColumns = item.Data.Cells.Count;
						}// Endif Cell count is greater than TotalColumns
					}
					else if (item is GridHeader)
					{
						if (item.Data.Cells.Count > TotalColumns)
						{
							TotalColumns = item.Data.Cells.Count;
						}
						item.CssClass = HeadRowClass;
						Controls.Add(item as GridHeader);
						Count++;
					}
					else if (item is GridFooter)
					{
						GridFooter footer = item as GridFooter;

						footer.GridData = Data;
						footer.RowsPerPage = RowsPerPage;
						footer.StartRow = StartRow;
						footer.ColumnSpan = TotalColumns;
						footer.TotalRecords = Data.Count.ToString();
						Controls.Add(footer);
					}
				}
			}

			return Count;
		}

		#endregion

		#region Data Binding Events

		protected override void OnDataBinding(EventArgs e)
		{
			base.OnDataBinding(e);
			GridEventArgs ge = e as GridEventArgs;
			// Check to see if we have some kind of header information to parse
			if (ge != null && ge.Data != null && ge.Data.Count > 0)
			{
				CreateChildControls(ge.Data, true);
			}// Endif EventArgs has data
		}// End method OnDataBinding

		#endregion
	}
}
